#pragma once

#pragma warning(disable: 4312)

#include <windows.h>
#include <mmsystem.h>

// this header inclues all the necessary D3D10 includes
//#include <dynlink_d3d10.h>

#include <DXUT/DXUT.h>
#include <DXUT/DXUTmisc.h>

// includes, cuda
#include <cuda.h>
#include <builtin_types.h>
#include <cuda_runtime_api.h>
#include <cuda_d3d10_interop.h>

// includes, project
#include <cutil_inline.h>
#include <rendercheck_d3d10.h>
#include "DistanceConstraint.h"

#include <Settings.h>
#include <Types.h>
#include <Util.h>
#include <fstream>
#include <vector>
#include "Simulator.h"


//#include <Vector4.h>
#define MAX_EPSILON 10

extern "C" void ExecuteIntegrate(void* pos, void* prevPos, unsigned int particleCount, float dt);

//extern "C" 
void ExecuteDistanceConstraintGPU(float4* pos, float4 *springs, unsigned int springCount, int iterations, float dt);

// testing/tracing function used pervasively in tests.  if the condition is unsatisfied
// then spew and fail the function immediately (doing no cleanup)
#define AssertOrQuit(x) \
    if (!(x)) \
{ \
    fprintf(stdout, "Assert unsatisfied in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
    return 1; \
}

class Game
{
public:
    Game(void);
    ~Game(void);

    void Run();

    void Initialize();
    void ResizeSwapChain(ID3D10Device* pd3dDevice, IDXGISwapChain* pSwapChain,
                                          const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext );
    void Update(float dt);
    void Draw(float dt);
    void Dispose();

    // Manejo de mouse.
    void OnMouseMove(int x, int y);
    void OnMouseLeftDown(int x, int y);
    void OnMouseLeftUp(int x, int y);
    void OnMouseWheel(int x, int y, int delta);

    
    int Width;
    int Height;

	Simulator *simulator;

    ID3D10Device*               device;
    IDXGISwapChain*             pSwapChain;
    ID3D10RenderTargetView*     pSwapChainRTV;

private:

    WNDCLASSEX wc;
    
    ID3D10InputLayout*          pInputLayout;
    ID3D10Effect*               pSimpleEffect;
    ID3D10EffectTechnique*      pSimpleTechnique;
    ID3D10EffectMatrixVariable* pmWorld;
    ID3D10EffectMatrixVariable* pmView;
    ID3D10EffectMatrixVariable* pmProjection;


    // Matrices de camara.
    Matrix World;
    Matrix View;
    Matrix Projection;

    //LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );

    
    HRESULT InitD3D();
    HRESULT InitGeometry();
    void InitCuda();


};
